package net.wicp.tams.commons.zookeeper.opt;

import static org.apache.zookeeper.CreateMode.EPHEMERAL_SEQUENTIAL;

import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;

import net.wicp.tams.commons.Result;
import net.wicp.tams.commons.zookeeper.IZKOpt;
import net.wicp.tams.commons.zookeeper.ZK;
import net.wicp.tams.commons.zookeeper.bean.ZNodeName;

public class ZKLockOpt implements IZKOpt {
	private final ZooKeeper zk = ZK.getInstance().getZk();
	private final String dir;
	private byte[] data = { 0x12, 0x34 };

	public ZKLockOpt(String dir) {
		this.dir = dir;
	}

	/***
	 * 返回第一个为 前一个路径 ，第二个为当前路径
	 */
	@Override
	public Result execute() throws KeeperException, InterruptedException {
		long sessionId = zk.getSessionId();
		final String prefix = String.format("x-%s-", sessionId);
		List<String> names = zk.getChildren(dir, false);

		CollectionUtils.filter(names, new Predicate() {
			@Override
			public boolean evaluate(Object object) {
				String name = String.valueOf(object);
				return name.startsWith("x-");
			}
		});

		String curNamePath = dir + "/" + prefix;
		if (CollectionUtils.isEmpty(names)) {
			String newPath = zk.create(curNamePath, data, Ids.OPEN_ACL_UNSAFE, EPHEMERAL_SEQUENTIAL);
			Result retobj = Result.getSuc();
			retobj.setRetObjs(null, newPath);
			return retobj;
		} else {
			ZNodeName curNode = null;
			SortedSet<ZNodeName> sortedNames = new TreeSet<ZNodeName>();
			for (String name : names) {
				if (name.startsWith(prefix)) {
					curNode = new ZNodeName(name);
				}
				sortedNames.add(new ZNodeName(name));
			}
			Object[] retAry = new Object[2];
			if (curNode == null) {// 没有找到当前节点
				String curPath = zk.create(curNamePath, data, Ids.OPEN_ACL_UNSAFE, EPHEMERAL_SEQUENTIAL);
				int tempIndex = curPath.indexOf(prefix);
				curNode = new ZNodeName(curPath.substring(tempIndex));
				sortedNames.add(curNode);
				retAry[1] = curPath;
				/*
				 * Result retobj = Result.getSuc(); retobj.setRetObjs(name);
				 * return retobj;
				 */
			} else {
				retAry[1] = dir + "/" + curNode.getName();
			}

			SortedSet<ZNodeName> lessThanMe = sortedNames.headSet(curNode);
			if (!lessThanMe.isEmpty()) {
				ZNodeName lastChildName = lessThanMe.last();
				String lastChildId = lastChildName.getName();
				retAry[0] = dir + "/" + lastChildId;
				/*
				 * Result retobj = Result.getSuc(); retobj.setRetObjs(dir + "/"
				 * + lastChildId); return retobj;
				 */
			} else {
				retAry[0] = null;
			}

			Result retobj = Result.getSuc();
			retobj.setRetObjs(retAry);
			return retobj;

		}
	}
}
